package cn.com.manager.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.IdentityService;
import org.activiti.engine.impl.persistence.entity.GroupEntity;
import org.activiti.engine.impl.persistence.entity.UserEntity;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import cn.com.manager.dao.MenuMapper;
import cn.com.manager.dao.RoleMapper;
import cn.com.manager.dao.UserMapper;
import cn.com.manager.page.PageInfo;
import cn.com.manager.pojo.Menu;
import cn.com.manager.pojo.MenuExample;
import cn.com.manager.pojo.Role;
import cn.com.manager.pojo.RoleExample;
import cn.com.manager.pojo.User;
import cn.com.manager.pojo.UserExample;
import cn.com.manager.pojo.UserExample.Criteria;
import cn.com.manager.pojo.UserSessionManager;
import cn.com.manager.service.SystemService;
import cn.com.manager.utility.ApplicationConstants;
import cn.com.manager.utility.PasswordHelper;

@Service
public class SystemServiceImpl implements SystemService {
	private static Logger logger = LoggerFactory.getLogger(SystemServiceImpl.class);

	@Autowired
	private UserMapper userMapper;
	@Autowired
	private RoleMapper roleMapper;
	@Autowired
	private PasswordHelper passwordHelper;
	@Autowired
	private SessionDAO sessionDAO;
	@Autowired
	private MenuMapper menuMapper;
	@Autowired
	private IdentityService identityService;

	@Override
	public User userInfoOfQuery(String username) {
		UserExample example = new UserExample();
		Criteria criteria = example.createCriteria();
		criteria.andAccountEqualTo(username);
		List<User> userList = userMapper.selectByExample(example);
		if (userList != null && !userList.isEmpty()) {
			return userList.get(0);
		}
		return null;
	}

	@Override
	@Transactional(value = "transactionManager", propagation = Propagation.REQUIRED)
	public User addOfUser(User user) {
		passwordHelper.encryptPassword(user);
		userMapper.insert(user);
		return user;
	}

	@Override
	public Collection<UserSessionManager> getUserSessions() {
		Collection<Session> activeSessions = sessionDAO.getActiveSessions();
		Collection<UserSessionManager> list = new ArrayList<>();
		for (Session session : activeSessions){
			PrincipalCollection principalCollection = (PrincipalCollection) session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
			if (principalCollection!=null){
				UserSessionManager bean = new UserSessionManager();
				bean.setSessionId(session.getId());
				bean.setHost(session.getHost());
				bean.setLastAccessTime(session.getLastAccessTime());
				bean.setUsername((String)principalCollection.getPrimaryPrincipal());
				bean.setLogout(session.getAttribute(ApplicationConstants.SESSION_LOGOUT) != null);
				list.add(bean);
			}
		}
		return list;
	}

	@Override
	public List<Map<String,Object>> searchMenu() {
		MenuExample example = new MenuExample();
		example.createCriteria().andIsQyEqualTo(1);
		example.setOrderByClause("sort");
		List<Menu> menus = menuMapper.selectByExample(example);
		List<Map<String,Object>> menuList = new ArrayList<>();
		for (Menu menu : menus){
			Map<String,Object> map = new HashMap<>();
			map.put("id",menu.getId());
			map.put("pId",menu.getpId());
			map.put("name",menu.getName());
			if (StringUtils.isNoneBlank(menu.getOpen())){
				map.put("open","1".equals(menu.getOpen()) ? true:false);
			}
			if (StringUtils.isNotBlank(menu.getFile())){
				map.put("file",menu.getFile());
			}
			map.put("icon", menu.getIcon());
			menuList.add(map);
		}
		return menuList;
	}

	@Override
	public List<Menu> searchMenuByLevel(int flag,String id) {
		MenuExample example = new MenuExample();
		List<Menu> list = null;
		if (flag == 0){
			example.createCriteria().andPIdEqualTo("0");
			list = menuMapper.selectByExample(example);
		}else if(flag == 1){
			example.createCriteria().andPIdEqualTo(id);
			list = menuMapper.selectByExample(example);
		}
		return list;
	}

	@Override
	public Menu searchMenuById(String id) {
		return menuMapper.selectByPrimaryKey(id);
	}

	@Override
	public int saveMenuInfo(Menu menu) {
		int result = 0;
		if (StringUtils.isNotBlank(menu.getId())){
			result = menuMapper.updateByPrimaryKeySelective(menu);
		}else{
			menu.setIcon(ApplicationConstants.icon_path+menu.getIcon());
			result = menuMapper.insertSelective(menu);
		}
		return result;
	}

	@Override
	@Transactional(value = "transactionManager", propagation = Propagation.REQUIRED)
	public void delMenuInfo(String id) {
		Menu menu = menuMapper.selectByPrimaryKey(id);

		MenuExample example = new MenuExample();
		if (StringUtils.equals("0",menu.getpId())){
			example.createCriteria().andPIdEqualTo(id);
			List<Menu> menus = menuMapper.selectByExample(example);
			for (Menu childMenu : menus){
				example.createCriteria().andPIdEqualTo(childMenu.getId());
				menuMapper.deleteByExample(example);
				menuMapper.deleteByPrimaryKey(childMenu.getId());
			}
		}else{
			example.createCriteria().andPIdEqualTo(id);
			menuMapper.deleteByExample(example);
			menuMapper.deleteByPrimaryKey(id);
		}
	}

	@Override
	public int saveRoleInfo(Role role) {
		int num = 0;
		if(StringUtils.isNotBlank(role.getRoleId())){
			num = roleMapper.updateByPrimaryKey(role);
			identityService.deleteGroup(role.getRoleId());
		}else{
			num = roleMapper.insertSelective(role);
		}
		if(num>0){
			GroupEntity group = new GroupEntity();
			group.setId(role.getRoleId());
			group.setName(role.getRoleName());
			identityService.saveGroup(group);
		}
		return num;
	}

	@Override
	public Role searchRoleById(String id) {
		return roleMapper.selectByPrimaryKey(id);
	}

	@Override
	public List<Role> search(Role role, PageInfo pageInfo) {
		RoleExample example = new RoleExample();
		if (role != null) {
			cn.com.manager.pojo.RoleExample.Criteria criteria = example.createCriteria();
			if (StringUtils.isNoneBlank(role.getRoleName())) {
				criteria.andRoleNameLike("%" + role.getRoleName() + "%");
			}
		}
		if (pageInfo != null) {
			Page<Role> results = PageHelper.startPage(pageInfo.getPageNo(), pageInfo.getPageSize(), true) .doSelectPage(() -> roleMapper.selectByExample(example));
			pageInfo.setCount((int) results.getTotal());
			return results.getResult();
		} else {
			return roleMapper.selectByExample(example);
		}
	}

	@Override
	public int removeRoleInfo(String id) {
		int num =roleMapper.deleteByPrimaryKey(id);
		if(num>0){
			identityService.deleteGroup(id);
		}
		return num;
	}

	@Override
	public List<User> search(User user, PageInfo pageInfo) {
		UserExample example = new UserExample();
		if (user != null) {
			Criteria criteria = example.createCriteria();
			if (StringUtils.isNoneBlank(user.getAccount())) {
				criteria.andAccountLike("%" + user.getAccount() + "%");
			}
		}
		if (pageInfo != null) {
			Page<User> results = PageHelper.startPage(pageInfo.getPageNo(), pageInfo.getPageSize(), true) .doSelectPage(() -> userMapper.selectByExample(example));
			pageInfo.setCount((int) results.getTotal());
			return results.getResult();
		} else {
			return userMapper.selectByExample(example);
		}
	}

	@Override
	public int removeUserInfo(String id) {
		int num = userMapper.deleteByPrimaryKey(id);
		if(num>0){
			identityService.deleteUser(id);
		}
		return num;
	}

	@Override
	public User searchUserById(String id) {
		return userMapper.selectByPrimaryKey(id);
	}

	@Override
	public int saveUserInfo(User user) {
		int num = 0;
		if(StringUtils.isNotBlank(user.getId())){
			num = userMapper.updateByPrimaryKeySelective(user);
			identityService.deleteUser(user.getId());
		}else{
			passwordHelper.encryptPassword(user);
			num = userMapper.insertSelective(user);
		}
		if(num>0){
			UserEntity userEntity = new UserEntity();
			userEntity.setId(user.getId());
			userEntity.setEmail(user.getEmail());
			userEntity.setFirstName(user.getAccount());
			identityService.saveUser(userEntity);
		}
		return num;
	}

	@Override
	public void saveUserBindRoles(String userId, String roleIds) {
		List<String> roleIdList = Arrays.asList(roleIds.split(","));
		String roleIdsOld = userMapper.selectRoleId(userId);
		if(StringUtils.isNoneBlank(roleIdsOld)){
			List<String> oldRoleList = Arrays.asList(roleIdsOld.split(","));
			oldRoleList.forEach(roleId -> {
				identityService.deleteMembership(userId, roleId);
			});
		}
		userMapper.deleteUserRoleBind(userId);
		roleIdList.forEach(roleId -> {
			Map<String,String> map = new HashMap<String,String>();
			map.put("userId", userId);
			map.put("roleId", roleId);
			userMapper.insertUserBindRole(map);
			identityService.createMembership(userId, roleId);
		});
	}
}
